|
sludgenz wrote: although separate AppDomains within the same process is looking like a promising line of inquiry too
Native code has no concept of AppDomains.
sludgenz wrote: I completely understand that loading the DLL into multiples instances in memory is an undesirable solution but it is the most desirable among the solutions that appear to be available
While technically it may be possible, it would be a daunting task to load multiple versions of a same DLL into different locations in the same process. Doing so would require re-implementing your own PE loader.
If I was going to use the “host the DLLs in a separate process” approach I’d use COM. When your local server calls CoRegisterClassObject[^] it would use the REGCLS_SINGLEUSE value of the REGCLS[^] enum to ensure each instance is in a separate process. Obviously you'd have to wrap the features you use from the DLL in COM interfaces.
Steve
|
|
|
|
|
Stephen Hewitt wrote: Native code has no concept of AppDomains.
Yes I know, but the process that actually loads the native .DLL is actually a .NET Windows Service (using interop to calll out to the native code).
Stephen Hewitt wrote: If I was going to use the “host the DLLs in a separate process” approach I’d use COM. When your local server calls CoRegisterClassObject[^] it would use the REGCLS_SINGLEUSE value of the REGCLS[^] enum to ensure each instance is in a separate process. Obviously you'd have to wrap the features you use from the DLL in COM interfaces.
I hadn't thought about using COM, thanks.
|
|
|
|
|
sludgenz wrote: Yes I know, but the process that actually loads the native .DLL is actually a .NET Windows Service (using interop to calll out to the native code).
The barriers between AppDomains are enforced when the MSIL is JITed and require the code to be verifiable. It will not help that the client is managed.
Steve
|
|
|
|
|
You can't without renaming the DLL. This is by design.
However, you could copy the DLL to new file with a different name and load that.
Anyone who thinks he has a better idea of what's good for people than people do is a swine.
- P.J. O'Rourke
|
|
|
|
|
Nasty, but little doubt the easiest way. Let's keep our eyes on the "Coding Horror" message board...
Steve
|
|
|
|
|
Yeah, it makes me want to throw up. But, he asked...
Anyone who thinks he has a better idea of what's good for people than people do is a swine.
- P.J. O'Rourke
|
|
|
|
|
i use a *.mkv file to learn matroska file format(anyone can get the information at www.matroska.org). but i encounter a question i don't know how to understand it. it's about block(Cluster->BlockGroup->Block):EBML Lacing. there is a block header provided:
A1 E5 82 00 00 06 07 9A AE BF BF BF BF BF DE04.....
according to the document, 0xA1 tells that the following data is a block,0xE5 tells the total length of this block is 0x65(=101d), 0x82 tells that the track entry is a audio track, following 0x0000 is its timecode, 0x06 indicates the block use EBML Lacing, 0x07 tells us there are 8 laces chunk following. So,the following 7 bytes should store the first 7 laces' sizes, right? if so, size[0]=0x1A, size[1]=0x1A+?, and how to calculate the others' size?
Maybe i loss some key information about it because of my bad english, so i hope someone would like to help me to have a look. Thanks.
|
|
|
|
|
i hope someone can explain that,because i encounter the same question about lacing construction,thanks very much!
|
|
|
|
|
I am glad to meet a friend with the same question. But, tell the truth, i have got the solution.
In my example:A1 E5 82 00 00 06 07 9A AE BF BF BF BF BF...
0xA1:header tag
0xE5: tell the total length of the block is 0x65=101
0x82: tell the block is a slice of track 2(known as trackentry in the document)
0x0000: timecode, two byte
0x06: tell the lacing type of the block used is EBML Lacing
0x07: the lacing slice in the block is 0x08=8, so the there will be 7 lacing-sizes given
0x9A: says the first size is stored in only one byte, size[0]=ebml_unsigned(0x9A)=0x1A=26
0xAE: the delta of the second size according to the first one, tells the first delta(size[1]-size[0] is stored in only one byte. delta=0xAE-0x80-3F=-0x11=-17, so, size[1]=size[0]+delta=26+(-17)=9
0xBF: delta=0xBF-0x80-0x3F=0, so size[2]=size[1]+delta=9+0=9 ==>size[2]=9
....so, we can calculate the rest: size[3]=9,size[4]=9,size[5]=9,size[6]=9
and size[7]=101(total size)-12(before the real data witch began after the last BF)-[26+9*6]=9
and in my example, the block precisely end with my calculated ends!
Note: Why we should minus 0x80 and 0x3F: you know, in ebml integer, the first '1'bit indicates how many bytes of the data used, so its no contribution to the final value.so if the integer is 1 byte, we minus 0x80, if 2 bytes, we minux 0x4000,...; after the first '1' bit is the sign bit, if the real value is negative, we should add the max value to code it. For 1 byte integer,its 1*xxxxxxb,*is the sign bit, so the max 1 byte integer is 2^6-1=0x3F(according to block_structure,so for a 2 bytes integer value val: real_val = val-0x4000-0x1FFF.
For more details, you can go www.matroska.org to looking for.
good luck
|
|
|
|
|
thanks for your patiently answers,I will carefully to see,looks like you have been very familiar with MKV,but,i still was a novice,so,if you don't mind,could i keep contact with you?MSN or QQ?Sorry to occupy your time.
best wishes
|
|
|
|
|
Take care, I am a newbie too. if you like, we can exchange more details via msn, my account is kcynice@hotmail.com
see you.
|
|
|
|
|
My progress dialog creates a worker thread using AfxBeginThread.
When the user clicks cancel, I don't want the window to close if the thread is still running. I want to have the thread safely finish first.
There is a BOOL variable that the worker thread checks on occasion while running. If this is true, it begins to cancel. The worker thread only reads this variable, the Progress Dialog writes to it if needed. Should the worker thread be suspended before this variable is written? Or will it be OK since they will never Write at the same time.
Secondly, and most importantly, I currently have the Worker Thread Post a WM_USER message, with certain WPARAM and LPARAM for the reason, when it has ended. Is there any other way to check if the thread is running or not, and what the controlling function's return value was?
Thanks
|
|
|
|
|
There are two methods. I've included code with both. I used a bool to signal the other thread, but vastly prefer using events since threads often have waits within them. Also note that I can't remember the last time I checked a thread exit code, but you may have a reason. Finally, if you don't call MFC within the thread (with a few exceptions), you could just use _beginthreadex(). I just did this last week.
1) Call AfxBeingThread() with the CREATE_SUSPENDED flag.
2) set CWinThread::m_bAutoDelete to false
3) Call CWinThread::Resume()
4) At exit, after setting the bool (or setting an event, which is my preferred method), call WaitOnSingleObject() with CWinThread::m_hThread
5) Call GetThreadExitCode() to get exit code
6) Delete the CWinThread object
I've run into problems with MFC complaining about item 6.
CWinThread* StartAfxThread(AFX_THREADPROC pThreadProc, LPVOID pParam = NULL, int priority = THREAD_PRIORITY_NORMAL)
{
CWinThread* pThread = ::AfxBeginThread(pThreadProc, pParam, priority, 0, CREATE_SUSPENDED);
pThread->m_bAutoDelete = false;
pThread->ResumeThread();
return pThread;
}
CWinThread* pThread = StartAfxThread(TheThread);
isRunning = false;
if (::WaitForSingleObject(pThread->m_hThread, 1000) == WAIT_TIMEOUT)
{
::TerminateThread(pThread->m_hThread, (DWORD) -1);
Sleep(10);
}
DWORD exitCode = 0;
::GetExitCodeThread(pThread->m_hThread, &exitCode);
_tprintf(_T("Exit code: %u"), exitCode);
delete pThread;
1) Call AfxBeingThread() with the CREATE_SUSPENDED flag.
2) Duplicate CWindThread::m_hThread
3) Call CWinThread::Resume()
4) At exit, after setting the bool, call WaitOnSingleObject() with the duplicate handle.
5) Call GetThreadExitCode() to get exit code
6) Close the duplicate handle
HANDLE StartAfxThread(AFX_THREADPROC pThreadProc, LPVOID pParam = NULL, int priority = THREAD_PRIORITY_NORMAL)
{
CWinThread* pThread = ::AfxBeginThread(pThreadProc, pParam, priority, 0, CREATE_SUSPENDED);
HANDLE hProcess = GetCurrentProcess();
HANDLE hDup;
if (!::DuplicateHandle(hProcess, pThread->m_hThread, hProcess, &hDup, 0, FALSE, DUPLICATE_SAME_ACCESS))
hDup = NULL;
pThread->ResumeThread();
return hDup;
}
HANDLE hThread = StartAfxThread(TheThread);
isRunning = false;
if (::WaitForSingleObject(hThread, 1000) == WAIT_TIMEOUT)
{
::TerminateThread(hThread, (DWORD) -1);
Sleep(10);
}
DWORD exitCode = 0;
::GetExitCodeThread(hThread, &exitCode);
_tprintf(_T("Exit code: %u"), exitCode);
CloseHandle(hThread);
Anyone who thinks he has a better idea of what's good for people than people do is a swine.
- P.J. O'Rourke
|
|
|
|
|
When the user clicks cancel, I don't want the window to close if the thread is still running. I want to have the thread safely finish first.
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
DWORD exitcode;
GetExitCodeThread(hTread->m_hThread, &exitcode);
if (exitcode != STILL_ACTIVE )
OnCancel();
-@SuDhIrKuMaR@-
|
|
|
|
|
By default a CWinThread object with auto delete itself upon thread exit. Not only will the thread handle within be invalid, the pointer itself will be invalid.
Anyone who thinks he has a better idea of what's good for people than people do is a swine.
- P.J. O'Rourke
|
|
|
|
|
hi all,
anyone have a idea the meaning of the bold lines.
using child pointer to a the parent class.
class CPolygon {
protected:
int width, height;
public:
void set_values (int a, int b)
{ width=a; height=b; }
//virtual int area (void) =0;
virtual int area (void)
{return 0;}
void printarea (void)
{ cout << this->area() << endl; }
};
class CTriangle: public CPolygon {
public:
int area (void)
{ return (width * height / 2); }
int test;
};
int main () {
CRectangle rect;
CTriangle trgl;
CPolygon * ppoly1 = ▭
CPolygon * ppoly2 = &trgl;
CTriangle * ptrgl = (CTriangle *) ▭
ppoly1->set_values (4,5);
ppoly2->set_values (4,5);
ptrgl->set_values (4,5);
ppoly1->printarea();
ppoly2->printarea();
ptrgl->printarea();
ptrgl->test = 1;
cout << ppoly1->area() << endl;
cout << ppoly2->area() << endl;
cout << ptrgl->area() << endl;
system("PAUSE");
return EXIT_SUCCESS;
}
|
|
|
|
|
The definition of CRectangle isn't present so I can't tell if the cast makes sense. I have to say it look like nonsense to me however. Also, as a general rule avoid C-style casts.
Steve
|
|
|
|
|
Let me restate my question
below code can be compile and run with no problem. but, i confused how the bold line works. I have not initialzed a CTriangle object in the bold line but i can access the data by a CTriangle pointer.
I dont think it is a good practice but i am quite confused how it works...
class CPolygon {
protected:
int width, height;
public:
void set_values (int a, int b)
{ width=a; height=b; }
virtual int area (void)
{return 0;}
void printarea (void)
{ cout << this->area() << endl; }
};
class CTriangle: public CPolygon {
public:
int area (void)
{ return (width * height / 2); }
int testdata;
};
int main () {
CPolygon poly;
CTriangle trgl;
CPolygon * ppoly2 = &trgl;
CTriangle * ptrgl = (CTriangle *) &poly;
ppoly2->set_values (4,5);
ptrgl->set_values (4,5);
ppoly2->printarea();
ptrgl->printarea();
ptrgl->testdata = 100;
cout << ppoly1->area() << endl;
cout << ppoly2->area() << endl;
cout << ptrgl->area() << endl;
cout << ptrgl->testdata << endl;
system("PAUSE");
return EXIT_SUCCESS;
}
|
|
|
|
|
The fact that it works is a fluke. The local poly is NOT a CTriangle . It just so happens that in the two classes the vtable[^] pointer is at the same location as are the first two members (width and height ). Accessing testdata (via ptrgl ) is wrong in this code. Also the wrong instance of virtual functions will be called. If I could give a single piece of advice to new C++ programmers it would be to stop casting yourself into strife.
Steve
|
|
|
|
|
I search the boards to no avail.
|
|
|
|
|
|
CString strText("GOOD");
char *pChar= (char *)(LPCTSTR)strText;
|
|
|
|
|
Please never suggest that unless you further elaborate.
Such conversion may be used only with extreme care.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
Do you mean to say i should elaborate what i have given there an an example?
|
|
|
|
|
I mean since your technique is dangerous hence you should explicitely state whenever it is viable.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|